##################################################################
# File : /lua/ui/dialogs/disconnect.lua
# Description : Handles multiplayer disconnects
# Author : GPG / Neruz
##################################################################

local UIUtil = import('/lua/ui/uiutil.lua')
local LayoutHelpers = import('/lua/maui/layouthelpers.lua')
local Text = import('/lua/maui/text.lua').Text
local Button = import('/lua/maui/button.lua').Button
local Bitmap = import('/lua/maui/bitmap.lua').Bitmap
local Group = import('/lua/maui/group.lua').Group
local LazyVar = import('/lua/lazyvar.lua').Create

local parent = false

local function ColumnMaxWidth(header, slots, field)
    return function ()
               local result = header.Width()
               for k,slot in slots do
                   local w = slot[field].Width()
                   if w > result then result = w end
               end
               return result
           end
end


function DestroyDialog()
    if parent then 
        parent:Destroy()
        parent = false
    end
end


local function CreateDialog(clients)

    DestroyDialog()

    parent = Group(GetFrame(0), "diconnectDialogParentGroup")
    parent.Depth:Set(GetFrame(0):GetTopmostDepth() + 10)
    parent:SetNeedsFrameUpdate(true)
        
    bg = Bitmap(parent, UIUtil.UIFile('/game/generic_brd/generic_brd_m.dds'))
    LayoutHelpers.FillParent(bg, parent)
            
    bgTopLeft = Bitmap(bg, UIUtil.UIFile('/game/generic_brd/generic_brd_ul.dds'))
    bgTopLeft.Bottom:Set(bg.Top)
    bgTopLeft.Right:Set(bg.Left)
            
    bgTopRight = Bitmap(bg, UIUtil.UIFile('/game/generic_brd/generic_brd_ur.dds'))
    bgTopRight.Bottom:Set(bg.Top)
    bgTopRight.Left:Set(bg.Right)
            
    bgBottomLeft = Bitmap(bg, UIUtil.UIFile('/game/generic_brd/generic_brd_ll.dds'))
    bgBottomLeft.Top:Set(bg.Bottom)
    bgBottomLeft.Right:Set(bg.Left)
            
    bgBottomRight = Bitmap(bg, UIUtil.UIFile('/game/generic_brd/generic_brd_lr.dds'))
    bgBottomRight.Top:Set(bg.Bottom)
    bgBottomRight.Left:Set(bg.Right)
            
    bgTopMid = Bitmap(bg, UIUtil.UIFile('/game/generic_brd/generic_brd_horz_um.dds'))
    bgTopMid.Bottom:Set(bg.Top)
    bgTopMid.Left:Set(bgTopLeft.Right)
    bgTopMid.Right:Set(bgTopRight.Left)
        
    bgBottomMid = Bitmap(bg, UIUtil.UIFile('/game/generic_brd/generic_brd_horz_lm.dds'))
    bgBottomMid.Top:Set(bg.Bottom)
    bgBottomMid.Left:Set(bgBottomLeft.Right)
    bgBottomMid.Right:Set(bgBottomRight.Left)
    
    bgLeftMid = Bitmap(bg, UIUtil.UIFile('/game/generic_brd/generic_brd_vert_l.dds'))
    bgLeftMid.Bottom:Set(bgBottomLeft.Top)
    bgLeftMid.Top:Set(bgTopLeft.Bottom)
    bgLeftMid.Right:Set(bgTopLeft.Right)
        
    bgRightMid = Bitmap(bg, UIUtil.UIFile('/game/generic_brd/generic_brd_vert_r.dds'))
    bgRightMid.Bottom:Set(bgBottomRight.Top)
    bgRightMid.Top:Set(bgTopRight.Bottom)
    bgRightMid.Left:Set(bgTopRight.Left)
            
    local dlgTitle = UIUtil.CreateText(bg, "<LOC UI_Disco0000>Connectivity", 16, UIUtil.bodyFont)
    LayoutHelpers.AtLeftTopIn(dlgTitle, parent)
        
    local headerGroup = Group(bg, "headerGroup")
    LayoutHelpers.Below(headerGroup, dlgTitle)
        
    local nameWidth = LazyVar()
    local ejectedByWidth = LazyVar()

    local nameHeader = UIUtil.CreateText(headerGroup, "<LOC UI_Disco0001>Player Name", 12, UIUtil.fixedFont)
    LayoutHelpers.AtLeftTopIn(nameHeader, headerGroup)
    nameHeader.Width:Set(120)

    local pingHeader = UIUtil.CreateText(headerGroup, "<LOC UI_Disco0003>Ping (ms)", 12, UIUtil.fixedFont)
    pingHeader.Top:Set(nameHeader.Top)
    pingHeader.Left:Set(function() return nameHeader.Left() + nameWidth() end)

    local quietHeader = UIUtil.CreateText(headerGroup, "<LOC UI_Disco0004>Quiet (m:s)", 12, UIUtil.fixedFont)
    LayoutHelpers.RightOf(quietHeader, pingHeader, 5)

    local ejectedByHeader = UIUtil.CreateText(headerGroup, '<LOC UI_Disco0006>Ejected by', 12, UIUtil.fixedFont)
    LayoutHelpers.RightOf(ejectedByHeader, quietHeader, 5)

    headerGroup.Height:Set(nameHeader.Height)
    headerGroup.Width:Set(function()
                              return nameWidth() + pingHeader.Width() + quietHeader.Width() + ejectedByWidth() + 15
                          end)

    local slots = {}
    local previous = headerGroup

    for i,client in clients do
        local slot = Group(bg, "clientSlotGroup " .. tostring(i))
        slots[i] = slot

        slot.index = i

        LayoutHelpers.Below(slot, previous)
        previous = slot

        slot.name = UIUtil.CreateText(slot, client.name, 12, UIUtil.fixedFont)
        slot.name.Left:Set(nameHeader.Left)
        slot.name.Top:Set(slot.Top)
        
        slot.ping = UIUtil.CreateText(slot, "", 12, UIUtil.fixedFont)
        slot.ping.Left:Set(pingHeader.Left)
        slot.ping.Top:Set(slot.Top)
        
        slot.quiet = UIUtil.CreateText(slot, "", 12, UIUtil.fixedFont)
        slot.quiet.Left:Set(quietHeader.Left)
        slot.quiet.Top:Set(slot.Top)
        
        slot.ejectedBy = UIUtil.CreateText(slot, '', 12, UIUtil.fixedFont)
        slot.ejectedBy.Left:Set(ejectedByHeader.Left)
        slot.ejectedBy.Top:Set(slot.Top)

        slot.bg = Bitmap(slot.name)
        slot.bg:SetSolidColor('c0000000')
        slot.bg.Top:Set(slot.name.Top)
        slot.bg.Bottom:Set(slot.name.Bottom)
        slot.bg.Left:Set(nameHeader.Left)
        slot.bg.Right:Set(function() return slot.ejectedBy.Left() + ejectedByWidth() end)
        slot.bg.Depth:Set(function() return slot.name.Depth() - 1 end)

        slot.eject = UIUtil.CreateButtonStd(slot, '/menus/profile-select', "<LOC UI_Disco0005>Eject From Game", 10, 0)
        slot.eject.Left:Set(slot.bg.Right)
        slot.eject.Top:Set(function() return slot.Top() - 6 end)
        slot.eject.OnClick = function(self, modifiers) EjectSessionClient(slot.index) end

        slot.Width:Set(function() return nameWidth() + pingHeader.Width() + quietHeader.Width() + ejectedByWidth() + slot.eject.Width() end)
        slot.Height:Set(function() return math.max(headerGroup.Height(), slot.eject.Height()) end)
    end

    nameWidth:Set(ColumnMaxWidth(nameHeader, slots, 'name'))
    ejectedByWidth:Set(ColumnMaxWidth(ejectedByHeader, slots, 'ejectedBy'))

    parent.Width:Set(function()
                         local maxWidth = 0
                         for k, v in slots do
                             if v.Width() > maxWidth then maxWidth = v.Width() end
                         end
                         if dlgTitle.Width() > maxWidth then maxWidth = dlgTitle.Width() end
                         if headerGroup.Width() > maxWidth then maxWidth = headerGroup.Width() end
                         return maxWidth
                     end)
    parent.Height:Set(function()
                          local height = 0
                          for k, v in slots do
                              height = height + v.Height()
                          end
                          height = height + dlgTitle.Height()
                          height = height + headerGroup.Height()
                          return height
                      end)
    LayoutHelpers.AtCenterIn(parent, GetFrame(0))

    function parent.Update(self, clients)
        for index, client in clients do
            local slot = slots[index]
            if client.connected then
                if client.quiet < 5000 then
                    slot.ping:SetText(string.format("%8d", client.ping))
                    slot.quiet:SetText('')
                else
                    slot.ping:SetText('--------')
                    local min = client.quiet / (1000 * 60)
                    local sec = math.mod(client.quiet / 1000, 60)
                    slot.quiet:SetText(string.format("%d:%02d",min,sec))
                end
            else
                slot.ping:SetText('')
                slot.quiet:SetText('')
            end
                
            local ejectedBy = ''
            for k, v in client.ejectedBy do
                if ejectedBy != '' then
                    ejectedBy = ejectedBy .. ', ' .. clients[v].name
                else
                    ejectedBy = clients[v].name
                end
            end
            slot.ejectedBy:SetText(ejectedBy)

            if client.connected and not client['local'] then
                if slot.eject:IsHidden() then slot.eject:Show() end
            else
                if not slot.eject:IsHidden() then slot.eject:Hide() end
            end
        end
    end

    UIUtil.MakeInputModal(parent, nil, nil)
end



function Update()

    local needDialog = false

    local clients = GetSessionClients()

    local stillin = {}
    for index,client in clients do
        if client.connected then
            table.insert(stillin,index)
        end
    end

    for index,client in clients do
        if client.quiet > 5000 then
            needDialog = true
        end
        if client.connected then
            if not table.equal(client.ejectedBy, {}) then
                needDialog = true
            end
        else
            if not table.equal(table.sorted(client.ejectedBy), stillin) then
                needDialog = true
            end
        end
    end

    if needDialog then
        if not parent then CreateDialog(clients) end
        parent:Update(clients)
    else
        if parent then DestroyDialog() end
    end

end
